<template>
    <div>
        <el-card style="margin: 20px 0">
            <CategorySelect
                @getCategoryId="getCategoryId"
                :isUse="!isShowTable"
            ></CategorySelect>
        </el-card>
        <el-card>
            <div v-show="isShowTable">
                <el-button
                    type="primary"
                    icon="el-icon-plus"
                    :disabled="!category3Id"
                    @click="addAttr"
                    >添加属性</el-button
                >
                <!-- 表格：展示平台属性 -->
                <el-table style="width: 100%" border :data="attrList">
                    <el-table-column
                        label="序号"
                        width="100"
                        type="index"
                        align="center"
                    >
                    </el-table-column>
                    <el-table-column
                        prop="attrName"
                        label="属性名称"
                        width="150"
                    >
                    </el-table-column>
                    <el-table-column label="属性值列表" width="width">
                        <template #default="{ row, $index }">
                            <el-tag
                                type="success"
                                v-for="(attrValue, index) in row.attrValueList"
                                :key="index"
                                style="margin: 0px 10px"
                                >{{ attrValue.valueName }}</el-tag
                            >
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" width="150">
                        <template #default="{ row, $index }">
                            <!-- 修改属性值 -->
                            <el-button
                                type="warning"
                                icon="el-icon-edit"
                                size="mini"
                                @click="editAttr(row)"
                            ></el-button>
                            <el-popconfirm
                                :title="`确定删除${row.attrName}吗?`"
                                @onConfirm="deleteAttr(row, $index)"
                            >
                                <el-button
                                    type="danger"
                                    icon="el-icon-delete"
                                    size="mini"
                                    slot="reference"
                                ></el-button>
                            </el-popconfirm>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
            <!-- 添加属性|修改属性的结构 -->
            <div v-show="!isShowTable">
                <el-form
                    :inline="true"
                    ref="form"
                    label-width="80px"
                    :model="attrInfo"
                >
                    <el-form-item label="属性名">
                        <el-input
                            placeholder="请输入属性名"
                            v-model="attrInfo.attrName"
                        ></el-input>
                    </el-form-item>
                </el-form>
                <el-button
                    type="primary"
                    icon="el-icon-plus"
                    @click="addAttrValue"
                    :disabled="!attrInfo.attrName"
                    >添加属性</el-button
                >
                <el-button @click="isShowTable = true">取消</el-button>
                <el-table
                    style="width: 100%; margin: 20px 0px"
                    border
                    :data="attrInfo.attrValueList"
                >
                    <el-table-column
                        label="序号"
                        width="80"
                        type="index"
                        align="center"
                    >
                    </el-table-column>
                    <el-table-column
                        label="属性值名称"
                        width="width"
                        prop="prop"
                    >
                        <template #default="{ row, $index }">
                            <!-- 这里的结构需要用到span和input进行来回的切换 -->
                            <el-input
                                size="mini"
                                placeholder="请输入属性值名称"
                                v-model="row.valueName"
                                v-if="row.flag"
                                @blur="toLook(row)"
                                @keyup.native.enter="toLook(row)"
                                :ref="$index"
                            ></el-input>
                            <span
                                v-else
                                @click="toEdit(row, $index)"
                                style="display: block"
                                >{{ row.valueName }}</span
                            >
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" width="width">
                        <template #default="{ row, $index }">
                            <!-- 气泡确认框 -->
                            <el-popconfirm
                                :title="`确定删除${row.valueName}吗?`"
                                @onConfirm="deleteAttrValue($index)"
                            >
                                <el-button
                                    type="danger"
                                    icon="el-icon-delete"
                                    size="mini"
                                    slot="reference"
                                ></el-button>
                            </el-popconfirm>
                        </template>
                    </el-table-column>
                </el-table>
                <el-button
                    type="primary"
                    @click="addOrUpdateAttr"
                    :disabled="attrInfo.attrValueList.length < 1"
                    >保存</el-button
                >
                <el-button @click="isShowTable = true">取消</el-button>
            </div>
        </el-card>
    </div>
</template>

<script>
// 按需引入lodash中的深拷贝
import cloneDeep from "lodash/cloneDeep"
export default {
    name: "Attr",
    data() {
        return {
            category1Id: "",
            category2Id: "",
            category3Id: "",
            // 接收平台属性数据
            attrList: [],
            // 是否显示表格
            isShowTable: true,
            // 收集新增属性|修改属性使用的
            attrInfo: {
                // 属性名
                attrName: "",
                // 属性值 因为属性值可以有多个因此用数组，每一个属性值都是一个对象需要attrId,valueName
                attrValueList: [],
                categoryId: 0, // 三级分类的id
                categoryLevel: 3, // 因为服务器也需要区分是几级id
            },
        }
    },
    methods: {
        // 自定义事件回调用来获取id
        getCategoryId({ categoryId, level }) {
            // 区分三级分类相应的id，以及父组件进行存储
            if (level == 1) {
                this.category1Id = categoryId
                // 一级id发生变化时清除二、三级id
                this.category2Id = ""
                this.category3Id = ""
            } else if (level == 2) {
                this.category2Id = categoryId
                // 二级id发生变化时清除三级id
                this.category3Id = ""
            } else {
                // 代表三级id都有了就可以法请求了
                this.category3Id = categoryId
                // 发请求获取平台的属性数据
                this.getAttrList()
            }
        },
        // 获取平台属性列表
        async getAttrList() {
            const { category1Id, category2Id, category3Id } = this
            // 发请求
            const result = await this.$API.attr.reqAttrInfoList(
                category1Id,
                category2Id,
                category3Id
            )
            if (result.code == 200) {
                this.attrList = result.data
            }
        },
        // 添加属性值的回调
        addAttrValue() {
            // 向属性值的数组里面添加元素
            // attrId:是相应属性的id，目前还没有相应的id，目前带给服务器的id为undefined
            // valueName:''相应的属性值的名称
            this.attrInfo.attrValueList.push({
                // 对于修改某一个属性的时候，可以在已有的属性值基础之上新增新的属性值（新增属性值的时候，需要把已有的属性id带上）
                attrId: this.attrInfo.id, // 相应的属性名的id
                valueName: "",
                // 给每一个属性值添加一个标记，用于单独控制切换查看和编辑模式
                flag: true,
            })
            // 最后一项聚焦
            this.$nextTick(() => {
                this.$refs[this.attrInfo.attrValueList.length - 1].focus()
            })
        },
        // 添加属性按钮的回调
        addAttr() {
            // 切换table的显示与隐藏
            this.isShowTable = false
            // 清除数据
            // 收集三级分类的id
            this.attrInfo = {
                attrName: "", // 属性名
                // 属性值 因为属性值可以有多个因此用数组，每一个属性值都是一个对象需要attrId,valueName
                attrValueList: [],
                categoryId: this.category3Id, // 三级分类的id
                categoryLevel: 3, // 因为服务器也需要区分是几级id
            }
        },
        // 修改属性值按钮的回调
        editAttr(attrObj) {
            this.isShowTable = false
            // 将选中的属性值合并 attrInfo
            // 由于数据结构当中存在多层引用对象，因此需要使用深拷贝解决这类问题
            this.attrInfo = cloneDeep(attrObj)
            // 在修改某一个属性的时候将相应的元素添加上flag标记
            this.attrInfo.attrValueList.forEach((item) => {
                // 这样书写也可以给属性值添加flag标记，但是会发现试图不会发生变化（因为flag不是响应式数据）
                // 直接=替换对象具有响应式,更改对象中某个已有的属性具有响应式,但后追加属性不具有响应式
                // 第一个参数：对象 第二个参数：响应式属性 第三个参数：新的属性的属性值
                this.$set(item, "flag", false)
            })
        },
        // 失去焦点的事件-----切换为查看模式，展示span
        toLook(row) {
            // row当前用户添加的最新属性
            if (row.valueName.trim() == "") {
                // 如果属性值为空不能作为新的属性值，需要给用户提示，让他输入一个其他的属性值
                this.$message({
                    message: "请您输入一个正常的属性值",
                    type: "warning",
                })
                return
            }
            // 新增的属性值不能与已有的属性值重复
            let isRepeat = this.attrInfo.attrValueList.some((item) => {
                // 需要将row从数组里面的判断的时候去除
                // row是最新增的属性值 这里判断主要是避免row和row判断
                if (row !== item) {
                    return row.valueName == item.valueName
                }
            })
            // 如果重复直接return，阻止后面的操作
            if (isRepeat) {
                this.$message({
                    message: "请您不要重复输入",
                    type: "warning",
                })
                return
            }
            // 当前编辑模式变为查看模式（让input消失、显示）
            row.flag = false
        },
        // 点击span切换成编辑模式的回调
        toEdit(row, index) {
            row.flag = true
            // 获取input节点，实现自动聚焦
            // 需要注意：点击span的时候，切换为input变为编辑模式，但是需要注意，对于浏览器而言，页面重绘与重拍是耗费时间的
            // 点击span的时候，页面重绘与重拍需要耗费时间，因此我们不可能一点击span获取input
            this.$nextTick(() => {
                this.$refs[index].focus()
            })
        },
        // 气泡确认框的确定按钮的回调
        // 最新版本的elementUI-----2.15.13 目前模板版本为2.13.2 所以使用onConfirm事件
        deleteAttrValue(index) {
            // 当前删除属性值操作不需要发送请求
            this.attrInfo.attrValueList.splice(index, 1)
        },
        // 保存属性信息:进行添加属性或者修改属性的操作
        async addOrUpdateAttr() {
            // 对信息进行过滤
            // 1.去除flag属性值 2.去除用户添加的空属性值
            this.attrInfo.attrValueList = this.attrInfo.attrValueList.filter(
                (item) => {
                    // 去除空属性
                    if (item.valueName != "") {
                        // 删除flag属性
                        delete item.flag
                        return true
                    }
                }
            )

            try {
                // 这里判断是避免过滤后的数组即使为空，也发送请求的情况
                if (this.attrInfo.attrValueList.length > 0) {
                    // 发请求
                    const result = await this.$API.attr.reqAddOrUpdateAttr(
                        this.attrInfo
                    )
                    // 气泡框提醒
                    this.$message({ type: "success", message: "保存成功！" })
                    // 重新获取数据
                    this.getAttrList()
                    // 切换table的显示与隐藏
                    this.isShowTable = true
                }
            } catch (error) {}
        },
        // 删除三级列表属性名称
        async deleteAttr(row, index) {
            // 获取属性id值
            const { id, attrName } = row
            try {
                // 发送删除请求
                const result = await this.$API.attr.reqDeleteAttr(id)
                // 弹出提示框
                this.$message({
                    type: "success",
                    message: `删除成功！`,
                })
                // 重新获取数据
                this.getAttrList()
            } catch (error) {}
        },
    },
}
</script>

<style>
</style>